import Config from "../config";
import { capitalizeFirstLetterOfEachWord } from "../utils/strings";

type ExceptionRule = { britishWord: string; exceptPreviousWords: string[] };
type BritishEnglishReplacements = Record<
  string /*EnglishWord*/,
  string /*BritishWord*/ | ExceptionRule
>;
const replacementRules: BritishEnglishReplacements = {
  laborers: "labourers",
  industrialized: "industrialised",
  acclimatizing: "acclimatising",
  acclimatized: "acclimatised",
  behoove: "behove",
  reorganization: "reorganisation",
  galvanize: "galvanise",
  demagogism: "demagoguism",
  canceled: "cancelled",
  baptize: "baptise",
  revitalize: "revitalise",
  skeptical: "sceptical",
  piscine: "piscinae",
  ionization: "ionisation",
  chili: "chilli",
  dexterous: "dextrous",
  likable: "likeable",
  neutralize: "neutralise",
  meter: "metre",
  meters: "metres",
  centimeter: "centimetre",
  hurrah: "hooray",
  multicolor: "multicolour",
  actualization: "actualisation",
  fertilizing: "fertilising",
  enamor: "enamour",
  skepticism: "scepticism",
  authorize: "authorise",
  minimize: "minimise",
  bandoleer: "bandolier",
  rigor: "rigour",
  fledgling: "fledgeling",
  mesquite: "mesquit",
  fogy: "fogey",
  characterize: "characterise",
  wagonette: "waggonette",
  plagiarize: "plagiarise",
  kilometers: "kilometres",
  molt: "moult",
  leveler: "leveller",
  checkered: "chequered",
  vendor: "vender",
  candor: "candour",
  moralize: "moralise",
  denationalization: "denationalisation",
  anemia: "anaemia",
  caiman: "cayman",
  chitterlings: "chitlins",
  acclimated: "acclimatised",
  acclimate: "acclimatise",
  skillful: "skilful",
  enamored: "enamoured",
  watercolor: "watercolour",
  extemporization: "extemporisation",
  lackluster: "lacklustre",
  equalizer: "equaliser",
  cipher: "cypher",
  polarization: "polarisation",
  polymerization: "polymerisation",
  ionize: "ionise",
  anesthetic: "anaesthetic",
  aerie: "eyrie",
  lachrymal: "lacrimal",
  decimeter: "decimetre",
  rajah: "raja",
  modernize: "modernise",
  gasoline: "petrol",
  alphabetized: "alphabetised",
  saber: "sabre",
  burglarize: "burglarise",
  terrorize: "terrorise",
  enthrall: "enthral",
  mustachioed: "moustachioed",
  anesthesia: "anaesthesia",
  sepulcher: "sepulchre",
  caftan: "kaftan",
  organize: "organise",
  manikin: "mannikin",
  dexterously: "dextrously",
  artifact: "artefact",
  kilometer: "kilometre",
  mommy: "mummy",
  brant: "brent",
  hyena: "hyaena",
  fuze: "fuse",
  victimize: "victimise",
  jihad: "jehad",
  airplane: "aeroplane",
  laborer: "labourer",
  vaporware: "vapourware",
  worshiped: "worshipped",
  taboret: "tabouret",
  rationalize: "rationalise",
  whimsy: "whimsey",
  scandalize: "scandalise",
  categorization: "categorisation",
  centered: "centred",
  kerosene: "kerosine",
  specialize: "specialise",
  specialized: "specialised",
  cicatrix: "cicatrice",
  jailer: "jailor",
  unfavorable: "unfavourable",
  guerrilla: "guerilla",
  emphasize: "emphasise",
  wacky: "whacky",
  ionizing: "ionising",
  czarina: "tzarina",
  ratline: "ratlin",
  abolitionize: "abolitionise",
  subsidize: "subsidise",
  plowing: "ploughing",
  untrammeled: "untrammelled",
  worshiping: "worshipping",
  memorization: "memorisation",
  anglicize: "anglicise",
  finalize: "finalise",
  gases: "gasses",
  fertilization: "fertilisation",
  libeling: "libelling",
  kinesthetic: "kinaesthetic",
  immunization: "immunisation",
  coloration: "colouration",
  overdraft: "overdraught",
  lambaste: "lambast",
  unpasteurized: "unpasteurised",
  ascendance: "ascendence",
  jeweler: "jeweller",
  fervor: "fervour",
  jeopardize: "jeopardise",
  abridgment: "abridgement",
  monopolize: "monopolise",
  colorless: "colourless",
  colorlessness: "colourlessness",
  tumors: "tumours",
  jinni: "jinn",
  aluminum: "aluminium",
  salable: "saleable",
  bronco: "broncho",
  lupine: "lupin",
  linchpin: "lynchpin",
  mesmerize: "mesmerise",
  internationalization: "internationalisation",
  anapestic: "anapaestic",
  supersede: "supercede",
  europeanize: "europeanise",
  optimized: "optimised",
  botanize: "botanise",
  organizational: "organisational",
  heme: "haem",
  estivation: "aestivation",
  edema: "oedema",
  penalize: "penalise",
  peddler: "pedlar",
  biased: "biassed",
  aggrandize: "aggrandise",
  rationalizing: "rationalising",
  deputize: "deputise",
  centers: "centres",
  unicolor: "unicolour",
  hypnotized: "hypnotised",
  anglicized: "anglicised",
  initialization: "initialisation",
  topee: "topi",
  nightie: "nighty",
  tricolor: "tricolour",
  reorganize: "reorganise",
  barbecue: "barbeque",
  fertilized: "fertilised",
  synthesize: "synthesise",
  economize: "economise",
  colter: "coulter",
  paleontologist: "palaeontologist",
  acclimatize: "acclimatise",
  idealize: "idealise",
  fossilization: "fossilisation",
  lionize: "lionise",
  acclimating: "acclimatising",
  luster: "lustre",
  demeanor: "demeanour",
  unauthorized: "unauthorised",
  smolder: "smoulder",
  abettor: "abetter",
  jewelry: "jewellery",
  demoralization: "demoralisation",
  fullness: "fulness",
  neighbored: "neighboured",
  neighbor: "neighbour",
  neighbors: "neighbours",
  neighboring: "neighbouring",
  neighborly: "neighbourly",
  neighborhood: "neighbourhood",
  neighborhoods: "neighbourhoods",
  magnetizer: "magnetiser",
  appetizer: "appetiser",
  hebraizing: "hebraising",
  carbonization: "carbonisation",
  favorably: "favourably",
  favorite: "favourite",
  behavioral: "behavioural",
  cognizant: "cognisant",
  skeptic: "sceptic",
  fiber: "fibre",
  fibers: "fibres",
  labeled: "labelled",
  analyze: "analyse",
  disorganization: "disorganisation",
  concenter: "concentre",
  categorize: "categorise",
  novelization: "novelisation",
  proselytize: "proselytise",
  draftsman: "draughtsman",
  paralyze: "paralyse",
  ostracize: "ostracise",
  italicize: "italicise",
  micrometer: "micrometre",
  cognizance: "cognisance",
  saltpeter: "saltpetre",
  conceptualization: "conceptualisation",
  containerization: "containerisation",
  anapest: "anapaest",
  leukemia: "leukaemia",
  omelet: "omelette",
  industrialize: "industrialise",
  characterization: "characterisation",
  amortize: "amortise",
  mazurka: "mazourka",
  macadamize: "macadamise",
  stymie: "stymy",
  analog: "analogue",
  prizer: "priser",
  cauterize: "cauterise",
  dysmenorrhea: "dysmenorrhoea",
  hippie: "hippy",
  mechanization: "mechanisation",
  commercialize: "commercialise",
  unsavory: "unsavoury",
  somber: "sombre",
  esophageal: "oesophageal",
  iodized: "iodised",
  tyrannize: "tyrannise",
  liberalize: "liberalise",
  computerization: "computerisation",
  synthesizer: "synthesiser",
  fertilizes: "fertilises",
  airdrome: "aerodrome",
  uncivilized: "uncivilised",
  mold: "mould",
  nitrogenized: "nitrogenised",
  legalize: "legalise",
  tantalize: "tantalise",
  eulogize: "eulogise",
  depolarization: "depolarisation",
  fecal: "faecal",
  bastardize: "bastardise",
  summarize: "summarise",
  cony: "coney",
  authorization: "authorisation",
  colorful: "colourful",
  temporized: "temporised",
  adviser: "advisor",
  tendinitis: "tendonitis",
  crystallization: "crystallisation",
  humor: "humour",
  humorous: "humourous",
  chanty: "shanty",
  dyspnea: "dyspnoea",
  aging: "ageing",
  mousy: "mousey",
  succor: "succour",
  distill: "distil",
  decentralization: "decentralisation",
  cauterization: "cauterisation",
  specter: "spectre",
  snowplow: "snowplough",
  pediatrics: "paediatrics",
  discoloration: "discolouration",
  tumor: "tumour",
  empathize: "empathise",
  pawpaw: "papaya",
  aggrandizement: "aggrandisement",
  fontanel: "fontanelle",
  brunet: "brunette",
  rumor: "rumour",
  epaulet: "epaulette",
  glycerin: "glycerine",
  fraternize: "fraternise",
  latinize: "latinise",
  sniveling: "snivelling",
  pasteurize: "pasteurise",
  modernization: "modernisation",
  patronize: "patronise",
  totaled: "totalled",
  normalization: "normalisation",
  niter: "nitre",
  shoveler: "shoveller",
  flier: "flyer",
  equalization: "equalisation",
  meagerly: "meagrely",
  favoritism: "favouritism",
  libelous: "libellous",
  popularized: "popularised",
  armory: "armoury",
  humanization: "humanisation",
  minuscule: "miniscule",
  collectible: "collectable",
  tepee: "teepee",
  stabilization: "stabilisation",
  moldy: "mouldy",
  colonize: "colonise",
  idealized: "idealised",
  meager: "meagre",
  armorer: "armourer",
  vitalize: "vitalise",
  fossilized: "fossilised",
  antagonize: "antagonise",
  criticize: "criticise",
  liter: "litre",
  stigmatize: "stigmatise",
  theorize: "theorise",
  combated: "combatted",
  desalination: "desalinisation",
  evangelize: "evangelise",
  idolization: "idolisation",
  smoldering: "smouldering",
  commercialization: "commercialisation",
  laureled: "laurelled",
  hematology: "haematology",
  fulfill: "fulfil",
  disorganized: "disorganised",
  accouterments: "accoutrements",
  busses: "buses",
  utilize: "utilise",
  enroll: "enrol",
  goiter: "goitre",
  stylized: "stylised",
  diarrhea: "diarrhoea",
  hypothesize: "hypothesise",
  esthetic: "aesthetic",
  dishonor: "dishonour",
  victualer: "victualler",
  paleolithic: "palaeolithic",
  sanatorium: "sanitarium",
  feminization: "feminisation",
  flotation: "floatation",
  teetotaler: "teetotaller",
  feudalization: "feudalisation",
  visualize: "visualise",
  fertilize: "fertilise",
  czar: "tzar",
  nationalization: "nationalisation",
  septicemia: "septicaemia",
  organizer: "organiser",
  recrystallization: "recrystallisation",
  dolor: "dolour",
  agonizing: "agonising",
  romanization: "romanisation",
  synchronize: "synchronise",
  amorist: "amourist",
  agonized: "agonised",
  belabor: "belabour",
  caster: "castor",
  softy: "softie",
  apothegm: "apophthegm",
  demobilization: "demobilisation",
  agonizes: "agonises",
  misdemeanor: "misdemeanour",
  recognizable: "recognisable",
  asshole: "arsehole",
  brutalization: "brutalisation",
  chamois: "shammy",
  clamor: "clamour",
  fertilizer: "fertiliser",
  deodorization: "deodorisation",
  privatization: "privatisation",
  tidbit: "titbit",
  molding: "moulding",
  alleluia: "halleluiah",
  canonization: "canonisation",
  customize: "customise",
  customization: "customisations",
  customizer: "customiser",
  customizers: "customisers",
  customizes: "customises",
  customizing: "customising",
  popularize: "popularise",
  specialty: "speciality",
  meagerness: "meagreness",
  esophagus: "oesophagus",
  millimeter: "millimetre",
  harmonization: "harmonisation",
  atomizer: "atomiser",
  dieresis: "diaeresis",
  maneuver: "manoeuvre",
  capitalize: "capitalise",
  gynecologist: "gynaecologist",
  acclimation: "acclimatisation",
  generalize: "generalise",
  temporize: "temporise",
  premunire: "praemunire",
  estival: "aestival",
  selvage: "selvedge",
  brier: "briar",
  hyperesthesia: "hyperaesthesia",
  maximize: "maximise",
  draftsmen: "draughtsmen",
  colonization: "colonisation",
  capitalization: "capitalisation",
  tenia: "taenia",
  paleontology: "palaeontology",
  libeler: "libeller",
  arytenoid: "arytaenoid",
  wainscoting: "wainscotting",
  globalization: "globalisation",
  legalization: "legalisation",
  magnetization: "magnetisation",
  stabilize: "stabilise",
  mesmerized: "mesmerised",
  savory: "savoury",
  reconnoiter: "reconnoitre",
  bastardized: "bastardised",
  rancor: "rancour",
  checker: "chequer",
  industrialization: "industrialisation",
  epitomize: "epitomise",
  socialize: "socialise",
  externalization: "externalisation",
  chivy: "chivvy",
  optimize: "optimise",
  romanize: "romanise",
  vulcanize: "vulcanise",
  plow: "plough",
  memorize: "memorise",
  sterilization: "sterilisation",
  routing: "routeing",
  raveling: "ravelling",
  savor: "savour",
  harmonize: "harmonise",
  cannibalize: "cannibalise",
  vaporize: "vaporise",
  utilization: "utilisation",
  hybridization: "hybridisation",
  mechanize: "mechanise",
  arbor: "arbour",
  arbors: "arbours",
  licorice: "liquorice",
  counselor: "counsellor",
  orthopedic: "orthopaedic",
  lusterless: "lustreless",
  numskull: "numbskull",
  paleozoic: "palaeozoic",
  malodor: "malodour",
  amenorrhea: "amenorrhoea",
  criticized: "criticised",
  gonorrhea: "gonorrhoea",
  fossilize: "fossilise",
  revolutionize: "revolutionise",
  woolen: "woollen",
  dishabille: "deshabille",
  organdy: "organdie",
  asses: "arses",
  furor: "furore",
  paycheck: "paycheque",
  pulverize: "pulverise",
  dramatization: "dramatisation",
  yodeler: "yodeller",
  apologize: "apologise",
  apologized: "apologised",
  blond: "blonde",
  oxidize: "oxidise",
  extemporize: "extemporise",
  whiz: "whizz",
  edile: "aedile",
  appall: "appal",
  legitimize: "legitimise",
  urbanization: "urbanisation",
  magnetize: "magnetise",
  womanize: "womanise",
  orthopedics: "orthopaedics",
  cognize: "cognise",
  christianization: "christianisation",
  vocalize: "vocalise",
  individualization: "individualisation",
  hemoglobin: "haemoglobin",
  racket: "racquet",
  agonize: "agonise",
  aggrandizes: "aggrandises",
  accouter: "accoutre",
  mollusk: "mollusc",
  publicize: "publicise",
  fraternization: "fraternisation",
  odorless: "odourless",
  odor: "odour",
  odorous: "odourous",
  rationalization: "rationalisation",
  pretense: "pretence",
  louver: "louvre",
  kopeck: "kopek",
  lissome: "lissom",
  idealization: "idealisation",
  nosy: "nosey",
  stogie: "stogy",
  althea: "althaea",
  immobilization: "immobilisation",
  majolica: "maiolica",
  savior: "saviour",
  civilize: "civilise",
  granddad: "grandad",
  centralization: "centralisation",
  localization: "localisation",
  evangelization: "evangelisation",
  ruble: "rouble",
  pajamas: "pyjamas",
  sterilize: "sterilise",
  math: "maths",
  localize: "localise",
  hospitalization: "hospitalisation",
  scrutinize: "scrutinise",
  acclimatization: "acclimatisation",
  misbehavior: "misbehaviour",
  behavior: "behaviour",
  color: "colour",
  tire: { britishWord: "tyre", exceptPreviousWords: ["will"] },
  gray: "grey",
  grays: "greys",
  theater: "theatre",
  amphitheater: "amphitheatre",
  center: "centre",
  realize: "realise",
  realizing: "realising",
  realization: "realisation",
  license: "licence",
  mom: "mum",
  "mom'l": "mum'll",
  favor: "favour",
  favors: "favours",
  favorites: "favourites",
  analyzed: "analysed",
  characterized: "characterised",
  colored: "coloured",
  colors: "colours",
  counseling: "counselling",
  customized: "customised",
  defense: "defence",
  offense: "offence",
  enrollment: "enrolment",
  flavor: "flavour",
  flavors: "flavours",
  flavoring: "flavouring",
  harbor: "harbour",
  harbored: "harboured",
  honor: "honour",
  honors: "honours",
  labor: "labour",
  licensed: "licenced",
  licenses: "licences",
  licensing: "licencing",
  modeling: "modelling",
  optimization: "optimisation",
  organization: "organisation",
  organizations: "organisations",
  organized: "organised",
  organizing: "organising",
  pediatric: "paediatric",
  personalized: "personalised",
  practice: "practise",
  realized: "realised",
  recognize: "recognise",
  recognized: "recognised",
  specialties: "specialities",
  specializing: "specialising",
  theaters: "theatres",
  travelers: "travellers",
  traveler: "traveller",
  traveling: "travelling",
  authorized: "authorised",
  behaviors: "behaviours",
  traveled: "travelled",
  utilizing: "utilising",
  utilized: "utilised",
  honored: "honoured",
  specializes: "specialises",
  practicing: "practising",
  signaling: "signalling",
  analyzing: "analysing",
  recognizes: "recognises",
  organizers: "organisers",
  visualization: "visualisation",
  standardized: "standardised",
  favorable: "favourable",
  analyzer: "analyser",
  recognizing: "recognising",
  uncategorized: "uncategorised",
  categorized: "categorised",
  vapor: "vapour",
  synchronization: "synchronisation",
  synchronized: "synchronised",
  rumors: "rumours",
  coloring: "colouring",
  honorable: "honourable",
  generalized: "generalised",
  generalization: "generalisation",
  mobilize: "mobilise",
  armor: "armour",
  armored: "armoured",
  labeling: "labelling",
  endeavor: "endeavour",
  civilized: "civilised",
  civilization: "civilisation",
  parlor: "parlour",
  tranquilize: "tranquilise",
  tranquillized: "tranquillised",
  tranquillization: "tranquillisation",
  catalog: "catalogue",
  cataloger: "cataloguer",
  cataloging: "cataloguing",
  catalogs: "catalogues",
  cataloged: "catalogued",
  uncataloged: "uncatalogued",
  catalogers: "cataloguers",
  discolored: "discoloured",
  discolor: "discolour",
  encyclopedias: "encyclopaedias",
  endeavored: "endeavoured",
  endeavors: "endeavours",
  endeavoring: "endeavouring",
  judgments: "judgements",
  judgment: "judgement",
  paneling: "panelling",
  defenses: "defences",
  criticizing: "criticising",
  mustache: "moustache",
  emphasized: "emphasised",
  emphasizes: "emphasises",
  emphasizing: "emphasising",
  fetus: "foetus",
  programs: "programmes",
  yogurt: "yoghurt",
  valor: "valour",
  moisturize: "moisturise",
  moisturized: "moisturised",
  moisturizes: "moisturises",
  moisturizing: "moisturising",
  favoring: "favouring",
  marvelous: "marvellous",
};

export async function replace(
  word: string,
  previousWord: string
): Promise<string> {
  // Convert American-style double quotes to British-style single quotes
  if (word.includes('"')) {
    word = word.replace(/"/g, "'");
  }

  if (word.includes("-")) {
    //this handles hyphenated words (for example "cream-colored") to make sure
    //we don't have to add every possible combination to the list
    return (
      await Promise.all(
        word.split("-").map(async (w) => replace(w, previousWord))
      )
    ).join("-");
  } else {
    const cleanedWord = word.replace(/^[\W]+|[\W]+$/g, "").toLowerCase();
    const rule = replacementRules[cleanedWord];

    if (rule === undefined) return word;

    const [britishWord, exceptions] =
      typeof rule === "string"
        ? [rule, []]
        : [rule.britishWord, rule.exceptPreviousWords];

    if (Config.mode === "quote" && exceptions.includes(previousWord)) {
      return word;
    }

    return word.replace(
      RegExp(`^(?:([\\W]*)(${cleanedWord})([\\W]*))$`, "gi"),
      (_, $1, $2, $3) =>
        $1 +
        (($2 as string).charAt(0) === ($2 as string).charAt(0).toUpperCase()
          ? $2 === ($2 as string).toUpperCase()
            ? britishWord.toUpperCase()
            : capitalizeFirstLetterOfEachWord(britishWord)
          : britishWord) +
        $3
    );
  }
}
